package app.common;

import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Enumeration;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.sql.DataSource;

import org.hibernate.Session;

public class DatabaseManager {
	static EntityManagerFactory emf;
	static DataSource ds;
	static String databaseUrl;

	public static void init() {
		String connMethod = (String) PropertyUtil.get(GlobalConstants.key_DBCONN_METHOD);
		if (GlobalConstants.value_DBCONN_METHOD_DRIVERMANABER.equals(connMethod)) {
			getEntityManagerFactory();
		} else if (GlobalConstants.value_DBCONN_METHOD_JNDI.equals(connMethod)) {
			getDataSource();
		}
		initDatabaseUrl();
	}

	static void getEntityManagerFactory() {
		String databaseMode = (String) PropertyUtil.get(GlobalConstants.key_databaseMode);
		if (GlobalConstants.value_databaseMode_embedded.equals(databaseMode)) {
			emf = Persistence.createEntityManagerFactory("derby_embedded");
		} else if (GlobalConstants.value_databaseMode_clientserver.equals(databaseMode)) {
			emf = Persistence.createEntityManagerFactory("derby");
		}
	}

	static DataSource getDataSource() {
		DataSource ds = null;
		try {
			Context ctx = new InitialContext();
			ds = (DataSource) ctx.lookup("java:comp/env/jdbc/TestDB");
			// System.out.println("DataSource:" + bds.getUrl() + "," +
			// bds.getDriverClassName());
		} catch (Exception e) {
			e.printStackTrace();
		}
		return ds;
	}

	public static void initDatabaseUrl() {
		try {
			databaseUrl = getConnection().getMetaData().getURL();
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}

	public static Connection getConnection() {
		Connection conn = null;
		if (emf != null) {
			EntityManager em = emf.createEntityManager();
			Session session = em.unwrap(Session.class);
			conn = session.connection();
		} else if (ds != null) {
			try {
				conn = ds.getConnection();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		return conn;
	}

	public static void shutdownDB() {
		try {
			String connMethod = (String) PropertyUtil.get(GlobalConstants.key_DBCONN_METHOD);
			if (GlobalConstants.value_DBCONN_METHOD_DRIVERMANABER.equals(connMethod)) {
				DriverManager.getConnection("jdbc:derby:;shutdown=true");
			}
		} catch (SQLException se) {
			if (se.getErrorCode() == 50000 && "XJ015".equals(se.getSQLState())) {
				System.out.println("Derby shutdown normally");
			} else {
				se.printStackTrace();
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				Enumeration<Driver> drivers = DriverManager.getDrivers();
				while (drivers.hasMoreElements()) {
					Driver driver = drivers.nextElement();
					DriverManager.deregisterDriver(driver);
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	public static void closeResource(ResultSet rs, Statement stmt, Connection conn) {
		if (rs != null) {
			try {
				rs.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		if (stmt != null) {
			try {
				stmt.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		if (conn != null) {
			try {
				conn.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	public static String getDatabaseUrl() {
		return databaseUrl;
	}
}
